/*
 * @File    :   executable.js
 * @Time    :   2024/03/11 16:12:54
 * @Author  :   chakcy
 * @Email   :   947105045@qq.com
 * @description   :   运行可执行文件
 */

// 导入所需模块
const { spawn } = require('child_process')
const { encode, decode } = require('../base64')
const fs = require('fs')

// 运行单个可执行程序并返回一个 Promise 对象
function runExecutable(executablePath, args) {
    if (typeof executablePath !== 'string' || typeof args !== 'object') {
        return Promise.reject(new Error('Invalid input. Expecting a string for executablePath and an array for args.'))
    }
    if (!fs.existsSync(executablePath)) {
        return Promise.resolve(new Error('The executable path does not exist.'))
    }
    return new Promise((resolve, reject) => {
        const process = spawn(executablePath, args)
        let output = ''

        // 处理标准输出流
        process.stdout.on('data', (data) => {
            output += data.toString()
        })

        // 处理错误输出流
        process.stderr.on('data', (data) => {
            console.error(`stderr from ${executablePath}: ${data}`)
            reject(new Error(`Error output from ${executablePath}: ${data}`))
        })

        // 处理进程错误
        process.on('error', (error) => {
            reject(error)
        })

        // 处理进程关闭
        process.on('close', (code) => {
            if (code === 0) {
                if (JSON.parse(decode(output))) {
                    output = JSON.parse(decode(output))
                } else {
                    output = decode(output)
                }
                resolve(output)
            } else {
                reject(new Error(`Executable ${executablePath} exited with code ${code}`))
            }
        })
    })
}

// 并行运行多个可执行程序并返回一个 Promise 对象
function runExecutablesInParallel(data) {
    if (!Array.isArray(data) || data.some(item => typeof item.path !== 'string' || typeof item.args !== 'object')) {
        return Promise.reject(new Error('Invalid input. Expecting an array of objects with path and args properties.'));
    }
    return Promise.all(data.map((item) => {
        // 将参数转为base64编码的 JSON 字符串
        const encodedJsonString = encode(item['args'])
        return runExecutable(item["path"], [encodedJsonString])
    })).then((results) => {
        return results
    }).catch(error => {
        // 捕获并处理错误
        console.error('An error occurred:', error)
        return Promise.reject(error)
    })
}

module.exports = {
    runExecutablesInParallel
}